#ifndef XCOMTASK_H
#define XCOMTASK_H
#include "XTask.h"
#include <string>
#include "XMsg.h"
struct bufferevent;
class XSSLCtx;
class XCOM_API XComTask : public XTask
{
public:
    XComTask();
    virtual ~XComTask();
    // 连接服务器，调用m_serverIP、m_servePort
    // 考录自动重连
    /**
     * XComTask类中的connect方法，用于建立到服务器的连接
     * 此方法首先设置服务器地址和端口，然后尝试通过bufferevent建立socket连接
     *
     * @return bool 表示连接是否成功建立
     */
    virtual bool connect();
    /**
     * @brief 初始化XComTask对象，设置通信套接字和事件回调。
     *
     * 该函数执行以下操作：
     * - 检查基础事件循环是否已创建。
     * - 获取并验证通信套接字的有效性。
     * - 创建一个新的缓冲事件对象，并设置读写回调和超时时间。
     * - 如果指定了服务器IP，则尝试连接到指定的服务器。
     *
     * @return bool 返回true表示初始化成功，返回false表示初始化失败。
     */
    bool Init() override final;
    // 关闭XCom任务
    // 该函数负责释放XComTask实例中持有的资源
    // 返回值为bool类型，但请注意，由于该函数始终返回true，其实际意义有限
    virtual bool Close();
    /**
     * XComTask类的事件回调函数，用于处理不同的网络事件
     * @param events 触发的事件类型，可以是多个事件的位组合
     */
    virtual void eventCB(short events);
    // connect成功时调用
    virtual void connectedCB();
    //
    virtual void readCB() = 0;
    //
    virtual void writeCB() {};
    // 激活写入回调
    virtual void BeginWrite();

    /**
     * 从bufferevent对象中读取数据
     *
     * @param data 存储读取数据的缓冲区指针
     * @param datasize 缓冲区的大小，指示可以读取的最大数据量
     * @return 读取的数据量，如果发生错误或达到文件末尾可能返回特殊值
     *
     * 此函数尝试从m_bev指向的bufferevent对象中读取数据如果m_bev未被正确设置，
     * 函数将记录错误信息并返回0，表示未进行读取操作这是为了确保m_bev是有效且准备就绪的
     *
     * 注意：此函数的实现假定m_bev成员变量和bufferevent_read函数的定义和行为
     */
    int Read(void *data, size_t size);
    /**
     * @brief 写入数据到bufferevent对象。
     *
     * 此函数将给定的数据块写入到m_bev指向的bufferevent对象中。它会检查m_bev、数据指针和数据大小的有效性，
     * 并调用bufferevent_write进行实际写入操作。如果任何检查失败或写入操作失败，函数将返回false。
     *
     * @param data 数据块的指针。
     * @param size 数据块的大小（以字节为单位）。
     * @return 成功返回true，失败返回false。
     */
    virtual bool write(const void *data, size_t size);
    // @brief 等待连接建立
    // @param timeout_sec: 超时时间（秒），用于限制等待连接的时间
    // @return 如果在指定时间内成功建立连接，则返回true；否则返回false
    bool waitConnected(int timeout_sec);
    /**
     * @brief 自动连接服务器
     * @param timeout_sec: 超时时间（秒），用于限制等待连接的时间
     * @return 如果在指定时间内成功建立连接，则返回true；否则返回false
     */
    bool autoConnect(int timeout_sec);

    void setServerIP(const char *ip);
    // 连接的服务器IP
    std::string serverIP() { return m_serverIP; }
    void setServerPort(unsigned short port) { m_servePort = port; }
    // 连接的服务器Port
    unsigned short servePort() { return m_servePort; }
    // 设置是否在关闭连接时删除该对象。会清理定时器事件
    void setDeleteOnClose(bool deleteOnClose) { m_deleteOnClose = deleteOnClose; }
    bool deleteOnClose() { return m_deleteOnClose; }
    // 设置是否自动连接服务器,默认不自动连接,设置
    void setAutoConnect(bool autoConnect)
    {
        m_autoConnect = autoConnect;
        if (m_autoConnect)
            setDeleteOnClose(false);
    }
    bool autoConnect() { return m_autoConnect; }
    bool isConnecting() { return m_isConnecting; }
    bool isConnected() { return m_isConnected; }
    // 设置定时器，只能有一个，需要在Init函数中调用
    virtual void setTimer(int ms);
    virtual void clearTimer();
    virtual void timerCB() {}

    virtual void setAutoConnectTimer(int ms);
    virtual void autoConnectTimerCB();
    virtual void clearAutoConnectTimer();
    virtual void clearAllTimer();
    void setSSLCtx(XSSLCtx *ctx)
    {
        m_sslCtx = ctx;
    }
    XSSLCtx *sslCtx()
    {
        return m_sslCtx;
    }
    // 必须再加入线程池前调用
    void set_read_timeout_ms_(int time_ms){
        read_timeout_ms_=time_ms;
    }
protected:
    bufferevent *m_bev = nullptr;
    // char m_readBuf[4096] = {0};
private:
    int read_timeout_ms_ = 0;
    /**
     * 初始化通信socket
     *
     * @param comsock 通信套接字描述符
     *
     * @return 成功返回true，失败返回false
     *
     * 此函数负责初始化一个bufferevent对象，用于处理通信套接字上的事件
     * 尝试创建一个新的bufferevent对象
     * 如果创建失败，记录错误信息并返回false
     * 成功创建后，设置bufferevent的回调函数，用于处理读、写和事件
     * 最后，启用bufferevent的读写事件处理功能
     * 如果启用事件处理成功，函数返回true，否则返回false
     */
    bool initBev(evutil_socket_t sock);
    // 客户端连接状态
    // 1-未处理 => 开始连接
    // 2-正在连接 => 等待连接成果
    // 3-已连接 => 做业务处理
    // 4-连接后失败 => 设计连接等待时间后开始连接
    bool m_isConnecting = true; // 是否正在连接
    bool m_isConnected = false; // 是否已经连接
    std::mutex *m_mutex = nullptr;
    // 服务器ip
    char m_serverIP[16] = {0};
    // 端口
    unsigned short m_servePort = 0;
    // 是否在调用Close时删除对象
    bool m_deleteOnClose = true;
    // 是否启动自动重连
    bool m_autoConnect = false;
    // 定时器事件close时不清理
    struct event *m_autoConnectTimerEvent = nullptr;
    struct event *m_timerEvent = nullptr;
    // SSL通信的上下文
    XSSLCtx *m_sslCtx = nullptr;
};

#endif // XCOMTASK_H
